#ifndef _ECMFS_CMN_
#define _ECMFS_CMN_

#define AES_KEYLEN 256
typedef enum my_bool_{
ECMFS_FALSE=0,
ECMFS_TRUE
} bool_ecmfs ;

typedef enum server_state_ {
    SERVER_STATE_UNKNOWN=0,
    SERVER_STATE_INITIALIZING,    
    SERVER_STATE_READY,
    SERVER_STATE_EDGE_READY,
    SERVER_STATE_CORE_READY,
    SERVER_STATE_INTERNAL_ERROR
}server_state_t;
typedef enum server_resp_ {
    SERVER_RESP_UNKNOWN=0,
    SERVER_RESP_HELLO,
    SERVER_RESP_WHOAREYOU,
    SERVER_RESP_SENDING_PUBKEY,
    SERVER_RESP_DONE,  
    SERVER_RESP_MOUNT_OK,     
    SERVER_RESP_ERROR,
    SERVER_NOTIFY_STATUS_UPDATE, 
    SERVER_NOTIFY_SESSION_UPDATE,
    SERVER_RESP_INTERNAL_ERROR
}server_resp_t;

typedef enum server_req_ {
    SERVER_OP_UNKNOWN=0,
    SERVER_OP_HELLO,
    SERVER_OP_STATUS_UPDATE,
    SERVER_OP_WHOAREYOU,
    SERVER_OP_SENDING_PUBKEY,
    SERVER_OP_DONE,    
    SERVER_OP_ERROR,    
    SERVER_OP_INTERNAL_ERROR
}server_req_t;

typedef enum node_type_ {
    NODE_NONE = 0,
    NODE_CLIENT,
    NODE_EDGE,
    NODE_CORE,
    NODE_MASTER
} node_type_t;

typedef enum client_op_ {
    CLIENT_OP_NONE = 0,
    CLIENT_OP_HELLO,
    CLIENT_OP_ADDUSER,
    CLIENT_OP_REMUSER,
    CLIENT_OP_MOUNT,
    CLIENT_OP_UNMOUNT
} client_op_t;

typedef enum master_op_ {
    MASTER_OP_NONE = 0,
    MASTER_OP_RESPONSE,
    MASTER_OP_NOTIFICATION,
    MASTER_OP_USERUPDATE,
    MASTER_OP_NODEUPDATE,
    MASTER_OP_SESSIONUPDATE,
    MASTER_OP_FAILOVER
} master_op_t;


typedef struct session_aes_key_ {
    char user_id[32];
    char user_ip[32];
    int  user_port;
    char edge_name[32];    
    char edge_ip[32];
    int  edge_port;
    unsigned char key[AES_KEYLEN/8];
    unsigned char iv[AES_KEYLEN/8];
} session_aes_key_t;

typedef struct edge_sessions_ { 
session_aes_key_t *sessList;
int sess_count;
int max_sessions;
}edge_sessions_t;

typedef struct ecmfs_message_ {
    int magic_num; /*19977991*/
    int to ;
    int from ; /* 1 - client
                   2 - edge
                   3 - core
                   4 - master
                 */
    int type;
                /* client: 1 -- add_user
                           2 -- remove_user
                           3 -- start_session
                           4 -- end_session
                   edge:   1 -- filegroup_sync
                           2 -- file_sync
                           3 -- report_error
                   core:   1 -- file_sync
                           2 -- report_error
                   master: 1 -- user_update
                           2 -- node_update
                           3 -- start_session
                           4 -- notify_error
                           5 -- failover_msg
                 */
     int  extra;                 
     int  message_len;
     char message[1];
} ecmfs_message_t;

typedef struct node_info_ {
    char node_name[32];
    node_type_t node_type;
    char node_ip[32];    
    int  node_port;
    int  node_pub_key_len;
    unsigned char node_pub_key[2048];
}node_info_t;

typedef struct ecmfs_runtime_state_ {
    server_state_t state;
    node_info_t info;
} ecmfs_runtime_state_t;

typedef struct ecmfs_msg_queue_node_ {
    int message_len;
    char *msg;
    int extra;
    struct ecmfs_msg_queue_node_ *next;
    struct ecmfs_msg_queue_node_ *previous;
} ecmfs_msg_queue_node_t;

typedef struct ecmfs_msg_queue_ {
int num_of_messages;  
pthread_mutex_t mq_mutex;
ecmfs_msg_queue_node_t *head;
ecmfs_msg_queue_node_t *tail;
} ecmfs_msg_queue_t;

typedef struct ecmfs_add_user_ {
    char user_id[32];
    int  user_pub_key_len;
    unsigned char user_pub_key[2048];
} ecmfs_add_user_t;

extern ecmfs_runtime_state_t ecmfs;
extern char *ecmfs_path;
void set_server_state(server_state_t newstate);
server_state_t get_server_state(void);
void dump_ecmfs_message(ecmfs_message_t *msg);
int copy_to_file(char *buffer, int buffer_len, char *file_name);
int copy_from_file(char *buffer, int *buffer_len, char *file_name);

int ecmfs_message_queue_count(ecmfs_msg_queue_t *ecmfs_mq);
int ecmfs_message_queue_del(ecmfs_msg_queue_t *ecmfs_mq,
                            char **msg, int *msgLen, int *extra);
int ecmfs_message_queue_add(ecmfs_msg_queue_t *ecmfs_mq,
                            void *msg, int msgLen, int extra);
ecmfs_msg_queue_t *ecmfs_message_queue_init(void);
void ecmfs_message_queue_deinit(ecmfs_msg_queue_t *ecmfs_mq);
void print_runtime_state(ecmfs_runtime_state_t *ecmfs);
void send_status_notifications(void);
int store_node_public_key(ecmfs_runtime_state_t *nodeState);
void send_response(int sd, void *arg,
            server_resp_t respType, bool_ecmfs  encrypted,
            node_type_t node_type);
int store_user_public_key(ecmfs_add_user_t *addMsg);


#endif/* _ECMFS_CMN_ */
